﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;//引入命名空间
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace _00_TCP客户端
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// 创建Socket对象用来完成TCP通讯
        /// </summary>
        Socket socketClient=null;

        public Form1()
        {
            InitializeComponent();
            ///取消跨线程访问控件
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //第一步：创建Socket对象
            //AddressFamily.InterNetwork：表示使用IPv4协议
            //SocketType.Stream：流式传输方式(将字符串转换成byte字节数组，然后传输)
            //ProtocolType.Tcp：表示使用TCP协议
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //第二步：设置连接的服务器IP地址和端口号 （服务器提供）
            IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(this.textBox1.Text), int.Parse(this.textBox2.Text));
            try
            {
                //第三步：连接服务器
                socketClient.Connect(iPEndPoint);
                //第四步：连接成功后，创建线程用以接收服务器发送过来的数据
                Task.Run(ReceiveMessage);
                //第五步：连接成功后，提示连接成功
                //修改显示颜色，提示成功
                this.richTextBox1.SelectionColor = Color.Green;
                this.richTextBox1.AppendText("连接服务器成功！\n");
                //关闭连接按钮
                this.button1.Enabled = false;
            }
            catch (Exception ex)
            {
                //修改显示颜色
                this.richTextBox1.SelectionColor = Color.Red;
                //连接失败，提示用户
                this.richTextBox1.AppendText("连接服务器失败！" + ex.Message + "\n");
            }
        }
        /// <summary>
        /// 接收服务器发送过来的数据
        /// </summary>
        public void ReceiveMessage()
        {
            while (true)
            {
                //创建byte数组用来接受数据， 1024*1024*2 表示最大接收2M的数据(建立缓冲区用以接收服务器发送过来的消息)
                byte[] buffer = new byte[1024 * 1024 * 2];
                try
                {
                    //接收服务器发送过来的数据,buffer为接收数据的缓冲区，由于是数组所以是引用传递=>阻塞当前线程，直到接收到数据
                    int length = socketClient.Receive(buffer); 
                    //判断是否接收到数据，如果长度为0，表示没有数据
                    if (length>0)
                    {
                        //提取第一个字节，判断数据类型
                        InfoType infoType = (InfoType)buffer[0];
                        switch (infoType)
                        {
                            case InfoType.None:
                                break;
                            case InfoType.HeartBeat:
                                break;
                            case InfoType.Message:
                                //将接收到的数据转换成字符串
                                //Encoding.Default.GetString 方法将byte数组转换成字符串，使用默认编码格式
                                //参数一：byte数组
                                //参数二：接收数据的起始位置
                                //参数三：接收数据的长度
                                string message = Encoding.Default.GetString(buffer, 1, length);
                                //修改显示颜色，显示接收到的数据
                                this.richTextBox1.SelectionColor = Color.Black;
                                this.richTextBox1.AppendText("接收到服务器发送过来的数据：" + message + "\n");
                                break;
                            case InfoType.JsonMessage:
                                break;
                            default:
                                break;
                        }

                    }
                }
                catch (Exception ex)
                {
                    //提示错误信息
                    this.richTextBox1.SelectionColor = Color.Red;
                    this.richTextBox1.AppendText("接收数据失败！" + ex.Message + "\n");
                    break;
                }

            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            socketClient?.Close();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //转换成byte数组
            byte[] buffer = Encoding.Default.GetBytes(this.textBox3.Text);
            //创建一个新的byte数组，长度为buffer的长度+1，第一位用于存储消息类型: InfoType
            byte[] newBuffer = new byte[buffer.Length + 1];
            //将消息类型存储在新数组的第一位
            newBuffer[0] = (byte)InfoType.Message;
            //将byte 复制到 newBuffer数组中，从第二位开始复制
            //Array.Copy 方法：将一个数组的元素复制到另一个数组中
            //参数一：源数组
            //参数二：源数组的起始位置
            //参数三：目标数组
            //参数四：目标数组的起始位置
            //参数五：要复制的元素个数
            Array.Copy(buffer, 0, newBuffer, 1, buffer.Length);
            //发送数据
            socketClient.Send(newBuffer);

        }
    }
}
